package com.njcb.ams.web.controller.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.njcb.ams.pojo.dto.standard.Response;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.util.AmsJsonUtils;
import org.apache.poi.ss.formula.EvaluationWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.factory.comm.DataBus;
import com.njcb.ams.util.AmsAssert;
import com.njcb.ams.util.AmsUtils;

/**
 * @author LOONG
 */
@RestController
public class FileUpDownloadController {
    private static final Logger logger = LoggerFactory.getLogger(FileUpDownloadController.class);
    /**
     * 设置上传文件最大值为2G，可以改为更大
     */
    public static final long FILE_MAX_SIZE = 2 * 1024 * 1024 * 1024;
    /**
     * 文件保存位置
     */
    public static String CURRENT_FILE_PATH = SysBaseDefine.SYS_FILE_TMP_PATH;
    private String contentDisposition = new String();
    /**
     * 允许上传的文件格式的列表
     */
    public static final String[] ALLOWED_EXT = new String[]{"txt", "log", "zip", "gz", "rar", "tar"};
    // public static final String[] ALLOWED_EXT = new String[] {};

    /**
     * 操作类型,INDEX:首页,UPLOAD:上传，DOWNLD:下载,FILELT：文件列表，DELETE:删除,UPLIST:上传页面
     */
    public static final String FILE_OPERATE_TYPE_TINDEX = "INDEX";
    public static final String FILE_OPERATE_TYPE_FILELT = "FILELT";
    public static final String FILE_OPERATE_TYPE_DELETE = "DELETE";
    public static final String FILE_OPERATE_TYPE_UPLIST = "UPLIST";

    public static final String UPDOWNLOAD_URL = "updownload.do";
    public static final String UPLOADFILE_URL = "uploadfile.do";
    public static final String DOWNLOADFILE_URL = "downloadfile.do";

    @RequestMapping(value = "updownload")
    @ResponseBody
    public void upDownLoad(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
        response.setDateHeader("Expires", 1);
        logger.info("操作人名称[" + DataBus.getUserName() + "],IP[" + request.getRemoteAddr() + "]");

        String cmd = request.getParameter("cmd");
        if (null == cmd || cmd.length() == 0) {
            cmd = FILE_OPERATE_TYPE_TINDEX;
        }
        String filedownpath = request.getParameter("filedownpath");
        if (null != filedownpath && filedownpath.trim().length() > 0) {
            CURRENT_FILE_PATH = filedownpath;
        }
        String filePath = request.getParameter("filePath");
        if (cmd.equals(FILE_OPERATE_TYPE_TINDEX)) {
            PrintWriter out = response.getWriter();
            out.println(indexHtml());
        } else if (cmd.equals(FILE_OPERATE_TYPE_FILELT)) {
            if (AmsUtils.isNotNull(filePath)) {
                CURRENT_FILE_PATH = filePath;
            }
            List<MyFile> fileList = new ArrayList<MyFile>();
            java.io.File localFile = new java.io.File(CURRENT_FILE_PATH);
            if (localFile.isFile()) {
                MyFile myFile = new MyFile(localFile);
                fileList.add(myFile);
            }
            if (localFile.isDirectory()) {
                java.io.File[] files = localFile.listFiles();
                if (null != files) {
                    for (int i = 0; i < files.length; i++) {
                        java.io.File file = files[i];
                        if (file.isDirectory()) {
                            // continue;
                        }
                        MyFile myFile = new MyFile(file);
                        fileList.add(myFile);
                    }
                }
            }
            PrintWriter out = response.getWriter();
            out.println(fileListHtml(fileList));
            return;
        } else if (cmd.equals(FILE_OPERATE_TYPE_DELETE)) {
            String fileName = request.getParameter("fileName");
            fileName = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
            java.io.File localFile = new java.io.File(CURRENT_FILE_PATH + fileName);

            boolean delSucc = localFile.delete();
            if (delSucc) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
                PrintWriter out = response.getWriter();
                out.println(" <html>");
                out.println("	<head> <title>删除失败</title> </head>");
                out.println("	此类型文件不允许删除");
                out.println(" </html>");
                out.println();
            }
            request.getRequestDispatcher("" + UPDOWNLOAD_URL + "?cmd=FILELT&rdnumber=" + new Random().nextLong())
                    .forward(request, response);
        } else if (cmd.equals(FILE_OPERATE_TYPE_UPLIST)) {
            PrintWriter out = response.getWriter();
            out.println(uploadHtml());
        }
    }

    /**
     * 文件上传接口
     * @param request
     * @param response
     * @param fileuppath
     * @param upfile
     * @throws Exception
     */
    @RequestMapping(value = "uploadfile")
    @ResponseBody
    public void uploadFile(HttpServletRequest request, HttpServletResponse response, String fileuppath,
                           @RequestParam("upfile") MultipartFile upfile) throws Exception {
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
        response.setDateHeader("Expires", 1);
        PrintWriter out = response.getWriter();
        // 上传文件名
        String fileName = upfile.getOriginalFilename();
        // 扩展名
        String extName = fileName.substring(fileName.lastIndexOf(".") + 1);

        logger.info("用户[{}]在客户端[{}]上传了文件[{}]", DataBus.getUserName(), request.getRemoteAddr(), fileName);

        // 目录结尾不是目录分隔符时、自动加上
        if ((fileuppath.lastIndexOf(File.separator) + 1) != fileuppath.length()) {
            fileuppath += File.separator;
        }

        //允许上传的扩展名
        List<String> resultList = new ArrayList<>(Arrays.asList(ALLOWED_EXT));
        if (!resultList.contains(extName)) {
            String msg = "只允许上传以下类型的文件:" + resultList.toString();
            out.println(AmsJsonUtils.objectToJson(Response.buildFail(msg)));
            return;
        }

        if (!upfile.isEmpty()) {
            // 上传文件路径
            File filepath = new File(fileuppath, fileName);
            // 判断路径是否存在，如果不存在就创建一个
            if (!filepath.getParentFile().exists()) {
                filepath.getParentFile().mkdirs();
            }
            // 将上传文件保存到一个目标文件当中
            upfile.transferTo(new File(fileuppath + File.separator + fileName));
        } else {
            out.println(AmsJsonUtils.objectToJson(Response.buildFail("未选择上传文件")));
            return;
        }

        String msg = "文件已保存为: " + upfile.getOriginalFilename() + "，文件大小: " + getFileSizeName(upfile.getSize());
        out.println(AmsJsonUtils.objectToJson(Response.buildSucc(msg)));
        return;
    }

    /**
     * 文件下载接口
     * @param request
     * @param response
     * @param paramMap
     * @throws Exception
     */
    @RequestMapping(value = "downloadfile")
    @ResponseBody
    public void downloadfile(HttpServletRequest request, HttpServletResponse response,
                             @SuppressWarnings("rawtypes") @RequestBody(required = false) Map paramMap) throws Exception {
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
        response.setDateHeader("Expires", 1);
        String fileName = "";
        if (AmsUtils.isNotNull(paramMap)) {
            fileName = (String) paramMap.get("fileName");
        }
        if (AmsUtils.isNull(fileName)) {
            fileName = request.getParameter("fileName");
        }

        AmsAssert.notNull(fileName, "文件没有找到.");
        response.setHeader("Content-Disposition", this.contentDisposition + " filename=" + fileName);

        // 复制缓冲区的大小
        int paramInt = 65000;
        ServletOutputStream os = response.getOutputStream();
        java.io.File localFile = new File(fileName);
        FileInputStream localFileInputStream = new FileInputStream(localFile);
        // 下载的文件长度
        long fileLength = localFile.length();
        byte[] arrayOfByte = new byte[paramInt];

        this.contentDisposition = ((this.contentDisposition == null) ? "attachment;" : this.contentDisposition);
        int i = 0;
        int j = 0;
        while (j < fileLength) {
            i = localFileInputStream.read(arrayOfByte, 0, paramInt);
            j += i;
            os.write(arrayOfByte, 0, i);
        }
        os.flush();
        os.close();

        logger.info("用户[{}]在客户端[{}]下载了文件[{}]", DataBus.getUserName(), request.getRemoteAddr(), fileName);
        response.setContentLength((int) fileLength);
        response.flushBuffer();
        localFileInputStream.close();
    }


    /**
     * 文件下载列表html
     * @param fileList
     * @return
     */
    private String fileListHtml(List<MyFile> fileList) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(" <html>");
        stringBuffer.append("	<head>");
        stringBuffer.append("		<title>文件列表</title> </head>");
        stringBuffer.append("		<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />");
        stringBuffer.append("	</head>");
        stringBuffer.append("	<tr><td><a href='" + UPDOWNLOAD_URL + "?cmd=INDEX' onClick=''>返回主页</a></td></tr>");
        stringBuffer.append("	<br/>");
        stringBuffer.append("	<form name=\"" + UPDOWNLOAD_URL + "\" method=\"post\" action='" + UPDOWNLOAD_URL
                + "?cmd=FILELT'>");
        stringBuffer.append("		<input type=\"text\" name=\"filedownpath\" value=\"" + CURRENT_FILE_PATH + "\"/>");
        stringBuffer.append("		<input type=\"submit\" name=\"submit\" value=\"切换目录\" />");
        stringBuffer.append("	</form>");
        stringBuffer.append("	<br/>");
        if (fileList.size() == 0) {
            stringBuffer.append("<tr><td>没有文件可下载</td></tr>");
        }
        for (int i = 0; i < fileList.size(); i++) {
            MyFile file = fileList.get(i);
            String fileName = file.getFile().getName();
            String fileNameFull = file.getFile().getAbsolutePath();
            String fileUrl = fileNameFull.replaceAll("\\\\", "%2F");
            fileUrl = fileUrl.replaceAll("/", "%2F");
            stringBuffer.append("<table border='1'>");
            stringBuffer.append("	<tr><td>文件名</td><td>" + file.getFile().getName() + "</td></tr>");
            stringBuffer.append("	<tr><td> 大小 </td><td>" + file.getSizeName() + "</td></tr>");
            if (file.getFile().isDirectory()) {
                stringBuffer.append("	<tr><td> 下载 </td><td>" + "<a href='" + UPDOWNLOAD_URL + "?cmd=FILELT&filePath="
                        + fileUrl + "' '>进入文件夹</a></td></tr>");
            } else {
                stringBuffer.append("	<tr><td> 下载 </td><td>" + "<a href='" + DOWNLOADFILE_URL + "?cmd=DOWNLD&fileName="
                        + fileUrl + "' '>点击下载</a></td></tr>");
            }
            stringBuffer.append("</table><br>");
        }
        stringBuffer.append(" </html>");
        return stringBuffer.toString();
    }

    /**
     * 显示文件大小
     */
    public static String getFileSizeName(long size) {
        Double fileSize = Double.valueOf(size);
        DecimalFormat df = new DecimalFormat("######.00");
        if (size < 1024L) {
            return df.format(fileSize) + " byte";
        } else if (size < 1048576L) {
            return df.format(fileSize.doubleValue() / 1024.0D) + "KB";
        }
        return df.format(fileSize.doubleValue() / 1024.0D / 1024.0D) + "MB";
    }


    /**
     * 首页页面
     *
     * @return
     */
    private String indexHtml() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(" <html>");
        stringBuffer.append(" 	<head> <title>文件上传下载</title> </head>");
        stringBuffer.append("	<body>");
        stringBuffer.append("		<a href=\"" + UPDOWNLOAD_URL + "?cmd=UPLIST\">文件上传</a>");
        stringBuffer.append("		<a href=\"" + UPDOWNLOAD_URL + "?cmd=FILELT\">文件下载</a>");
        stringBuffer.append("	</body>");
        stringBuffer.append(" </html>");
        return stringBuffer.toString();
    }

    /**
     * 上传页面
     *
     * @return
     */
    private String uploadHtml() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(" <html><head>");
        stringBuffer.append("	<title>文件上传</title>");
        stringBuffer.append(" </head>");
        stringBuffer.append(" <body>");
        stringBuffer.append("	<p>&nbsp;");
        stringBuffer.append("	<form name=\"" + UPLOADFILE_URL + "\" method=\"post\" action='" + UPLOADFILE_URL
                + "?cmd=UPLOAD' ENCTYPE=\"multipart/form-data\"  target=\"upload_frame\">");
        stringBuffer.append("		<div id=\"formDiv\">");
        stringBuffer.append("			<div>");
        stringBuffer.append("			<b>上传目录</b> <input type=\"text\" name=\"fileuppath\" value=\"" + CURRENT_FILE_PATH + "\"/>");
        stringBuffer.append("			</div>");
        stringBuffer.append("			<div id=\"uploadedFiles\">");
        stringBuffer.append("			</div>");
        stringBuffer.append("			<div>");
        stringBuffer.append("				<b>选择文件</b> <input type=\"file\" id=\"upfile\" name=\"upfile\" size=\"50\"/><br/>");
        stringBuffer.append("			</div>");
        stringBuffer.append("			<div id=\"button\">");
        stringBuffer.append("				<input type=\"submit\" name=\"submit\" value=\"上传\" id=\"uploadbutton\"/><br/>");
        stringBuffer.append("			</div>");
        stringBuffer.append("		</div>");
        stringBuffer.append("	</form>");
        stringBuffer.append("	<div align=\"left\"><a href='" + UPDOWNLOAD_URL + "?cmd=INDEX' onClick=''>返回主页</a></div>");
        stringBuffer.append("	<br/>");
        stringBuffer.append(" </body>");
        stringBuffer.append(" </html>");
        return stringBuffer.toString();
    }

    class MyFile {
        private String sizeName;
        private java.io.File file;

        public MyFile() {
        }

        public MyFile(java.io.File file) {
            this.file = file;
            this.sizeName = getFileSizeName(file.length());
        }

        public void setSizeName(String sizeName) {
            this.sizeName = sizeName;
        }

        public String getSizeName() {
            return sizeName;
        }

        public void setFile(java.io.File file) {
            this.file = file;
        }

        public java.io.File getFile() {
            return file;
        }
    }

}
